home *** CD-ROM | disk | FTP | other *** search
- /* OS- and machine-dependent stuff for IBM-PC running MS-DOS and Turbo-C */
- #include <stdio.h>
- #include <conio.h>
- #include <dir.h>
- #include <dos.h>
- #include <io.h>
- #include <sys/stat.h>
- #include <string.h>
- #include <process.h>
- #include <fcntl.h>
- #include <alloc.h>
- #include <stdarg.h>
- #include <bios.h>
- #include "global.h"
- #include "config.h"
- #include "mbuf.h"
- #include "socket.h"
- #include "internet.h"
- #include "iface.h"
- #include "cmdparse.h"
- #include "pc.h"
- #include "proc.h"
- #include "session.h"
- #include "smtp.h"
- #ifdef SCC
- #include "scc.h"
- #endif
- #ifdef PACKET
- #include "pktdrvr.h"
- #endif
- #ifdef ASY
- #include "asy.h"
- #include "8250.h"
- #endif
- #include "domain.h"
-
- #define DEL 0x7f
-
- static int near kbchar __ARGS((void));
-
- extern struct proc *Display;
- extern struct timer Statustimer;
-
- int Tick;
- static int32 Starttime;
- int32 Clock;
-
- /* This flag is set by setirq() if IRQ 8-15 is used, indicating
- * that the machine is a PC/AT with a second 8259 interrupt controller.
- * If this flag is set, the interrupt return code in pcgen.asm will
- * send an End of Interrupt command to the second 8259 as well as the
- * first.
- */
- int Isat = 0;
-
- static char Tsbuf[BUFSIZ];
- static int saved_break;
-
- #define KBSIZE 256 /* Keyboard input buffer */
-
- static struct {
- char buf[KBSIZE];
- char *wp;
- char *rp;
- int cnt;
- } Keyboard;
-
- static int Swap = 0;
- static long near bioscnt __ARGS((void));
- static int near _spawn __ARGS((int mode,char *env,char *def,int argc,char *argv[]));
- extern int do_spawn __ARGS((int swapping,char *execfname,char *cmdtail,unsigned envlen,char *envp));
- extern int prep_swap __ARGS((unsigned method,char *swapfname));
-
- /* Directly read BIOS count of time ticks. This is used instead of
- * calling biostime(0,0L). The latter calls BIOS INT 1A, AH=0,
- * which resets the midnight overflow flag, losing days on the clock.
- */
- static long near
- bioscnt()
- {
- int i_state = dirps();
- long rval = *(long far *)MK_FP(0x40,0x6c);
- restore(i_state);
- return rval;
- }
-
- #ifdef MSDOS
- /*
- * define the error messages for trapping disk problems - D.Crompton
- * ported into WNOS DB3FL.910407
- */
- static int
- errhandler(int errval,int ax,int bp,int si)
- {
- char *crit_err_msg[] = {
- "write protect",
- "unknown unit",
- "not ready",
- "unknown command",
- "data error (CRC)",
- "bad request",
- "seek error",
- "unknown media type",
- "sector not found",
- "printer out of paper",
- "write fault",
- "read fault",
- "general failure",
- "reserved",
- "reserved",
- "invalid disk change"
- };
- char msg[80];
- int drive, errorno;
- unsigned di = _DI;
-
- if (ax < 0) {
- hardretn(3);
- return 3;
- }
- drive = ax & 0x00FF;
- errorno = di & 0x00FF;
- sprintf(msg,"\n\rError: %s on drive %c\n\r$",
- crit_err_msg[errorno], 'A' + drive);
- bdosptr(0x09,msg,0);
- hardretn(3);
- return 3;
- }
- #else
- static int
- errhandler(errval,ax,bp,si)
- int errval,ax,bp,si;
- {
- return 3; /* Fail the system call */
- }
- #endif /* MSDOS */
-
- /* Called at startup time to set up console I/O, memory heap */
- void
- ioinit()
- {
- extern int getproc __ARGS((void));
-
- /* Fail all I/O errors */
- harderr(errhandler);
-
- /* Save these two file table entries for something more useful */
- fclose(stdaux);
- fclose(stdprn);
- setbuf(stdout,Tsbuf);
-
- /* this breaks tab expansion so you must use ANSI or NANSI */
- ioctl(fileno(stdout), 1, (ioctl(fileno(stdout),0) & 0xff) | 0x20);
- saved_break = getcbrk();
- setcbrk(0);
-
- Starttime = bioscnt();
- /* Link timer handler into timer interrupt chain */
- chtimer(btick);
-
- /* Find out what multitasker we're running under, if any */
- chktasker();
-
- Isat = (getproc() > 5);
-
- /* Initialize keyboard queue */
- Keyboard.rp = Keyboard.wp = Keyboard.buf;
-
- }
- /* Called just before exiting to restore console state */
- void
- iostop()
- {
- struct iface *ifp, *iftmp = 0;
-
- ioctl(fileno(stdout), 1, (ioctl(fileno(stdout), 0) & 0xff) & ~0x20);
- setcbrk(saved_break);
-
- for(ifp = Ifaces;ifp != NULLIF;ifp = iftmp){
- iftmp = ifp->next;
- if_detach(ifp);
- }
- #ifdef SCC
- sccstop(); /* reset int mask for all scc boards */
- #endif
- /* Unlink timer handler from timer chain */
- uchtimer();
- }
-
- /*-----------------------------------------------------------------------*/
- typedef struct {
- struct text_info tr;
- char *sbuf;
- }Doslock;
-
- static unsigned near dos_prepare(Doslock *dl);
- static void near dos_restore(Doslock *dl);
- /* static unsigned near getmaxfree(void); */
-
- static int do_exec __ARGS((char *xfn,char *pars,int spawn,unsigned needed));
-
- /* Return codes (only upper byte significant) */
-
- #define RC_PREPERR 0x0100
- #define RC_NOFILE 0x0200
- #define RC_EXECERR 0x0300
- #define RC_ENVERR 0x0400
- #define RC_SWAPERR 0x0500
-
- /* Swap method and option flags */
-
- #define USE_EMS 0x01
- #define USE_XMS 0x02
- #define USE_FILE 0x04
- #define EMS_FIRST 0x00
- #define XMS_FIRST 0x10
- #define HIDE_FILE 0x40
- #define NO_PREALLOC 0x100
- #define CHECK_NET 0x200
-
-
-
- #define USE_ALL (USE_EMS | USE_XMS | USE_FILE)
-
-
-
- static int dexists (char *filename)
- {
- struct stat stbuf;
- return (stat (filename, &stbuf) != -1) ? 1 : 0;
- }
-
- static int near
- _spawn(int mode,char *env,char *def,int argc,char *argv[])
- {
- Doslock dl;
- int ret = 0;
- char *command, *p;
-
- if((p = getenv(env)) == NULLCHAR)
- p = def;
-
- dos_prepare(&dl);
-
- if (!Swap || Mtasker) {
- if (argc < 2)
- system(p);
- else
- ret = spawnvp(P_WAIT,argv[1],argv + 1);
- } else {
- if (argc > 1) {
- if((command = mxallocw(256)) != NULLCHAR) {
- int i;
- strcat(command,"/c ");
- for(i = 1; i < argc; i++) {
- strcat(command,argv[i]);
- strcat(command," ");
- }
- do_exec (p, command, USE_ALL, 0xffff);
- xfree (command);
- }
- } else
- do_exec (p, "", USE_ALL, 0xffff);
- }
-
- dos_restore(&dl);
-
- return ret;
- }
-
- /*----------------------------------------------------------------------*
- *-----------------------------------------------------------------------*/
- int dobmail(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int ret;
-
- ret = _spawn(1,"MAILER","BM.EXE",argc,argv);
- /*-------------------------------------------------------------------*
- * process Mailprompts *
- *--------------------------------------------------------------------*/
- smtptick(NULL); /* tickle smtp to send any mail */
- return ret;
- }
-
- #ifdef XXX
- /*----------------------------------------------------------------------*
- * Spawn dg4dam's NNVIEW as subshell *
- *-----------------------------------------------------------------------*/
- int donntpview(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
-
- return (_spawn(1,"NNTPVIEW","NNTPVIEW.EXE",argc,argv));
-
- }
- #endif
-
- int doshell(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return _spawn(1,"COMSPEC","COMMAND.COM",argc,argv);
- /*-------------------------------------------------------------------*
- * .... spawn the subshell *
- *--------------------------------------------------------------------*/
- /*
- if(argc == 1 || !stricmp(argv[1], "/c")) {
- return _spawn(1,0,0,argv);
- } else
- return _spawn(1,0,0,argv);
- */
- }
-
- /*----------------------------------------------------------------------*
- *-----------------------------------------------------------------------*/
-
- #define SWAP_FILENAME "$$AAAAAA.AAA"
-
- /* internal flags for prep_swap */
-
- #define CREAT_TEMP 0x0080
- #define DONT_SWAP_ENV 0x4000
-
- static int do_exec (char *exfn, char *epars, int spwn, unsigned needed)
- {
- static char swapfn [82];
- static char execfn [82];
- unsigned avail;
- union REGS regs;
- int rc, idx, swapping;
-
- strcpy (execfn, exfn);
-
- if (!spwn)
- swapping = -1;
- else {
-
- /*----------------------------------------------------------------*
- * Determine amount of free memory *
- *-----------------------------------------------------------------*/
- regs.x.ax = 0x4800;
- regs.x.bx = 0xffff;
- intdos (®s, ®s);
- avail = regs.x.bx;
-
- /*----------------------------------------------------------------*
- * No swapping if available memory > needed *
- *-----------------------------------------------------------------*/
- if (needed < avail)
- swapping = 0;
- else {
- /* Swapping necessary, use 'TMP' or 'TEMP' environment variable
- to determine swap file path if defined. */
-
- swapping = spwn;
- if (spwn & USE_FILE) {
- char *temp = getenv("TEMP");
- strcpy (swapfn,(temp != NULLCHAR) ? temp : "");
-
- if (_osmajor >= 3)
- swapping |= CREAT_TEMP;
- else {
- strcat (swapfn, SWAP_FILENAME);
- idx = strlen (swapfn) - 1;
- while (dexists (swapfn)) {
- if (swapfn[idx] == 'Z')
- idx--;
- if (swapfn[idx] == '.')
- idx--;
- swapfn[idx]++;
- }
- }
- }
- }
- }
-
- /* All set up, ready to go. */
-
- if (swapping > 0) {
- swapping |= DONT_SWAP_ENV;
-
- rc = prep_swap (swapping, swapfn);
- if (rc < 0)
- return RC_PREPERR | -rc;
- }
-
- rc = do_spawn (swapping, execfn, epars, 0,0);
-
- return rc;
- }
-
- static unsigned near
- dos_prepare(Doslock *dl)
- {
- /*-------------------------------------------------------------------*
- * save the current screen layout *
- *--------------------------------------------------------------------*/
- gettextinfo(&dl->tr);
-
- if ((dl->sbuf = mxallocw(2*dl->tr.screenheight*dl->tr.screenwidth))==0)
- return(0);
-
- gettext(dl->tr.winleft, dl->tr.wintop,
- dl->tr.winright, dl->tr.winbottom,
- dl->sbuf);
-
- /*-------------------------------------------------------------------*
- * temporarily suspend all our irq's *
- * SEE THE CHANGES IN THE PARTICULAR xxx_init() and xxx_stop rtns. *
- * dk5dc *
- *--------------------------------------------------------------------*/
- if (Swap) {
- #ifdef ASY
- int i;
- struct asy *asyp;
-
- for(i=0;i < ASY_MAX;i++){ /* scan the asy structures */
- asyp = &Asy[i];
- if(asyp->iface == NULLIF)
- continue;
- asy_stop(asyp->iface,1); /* note:changes in 8250.c dk5dc */
- }
- #endif
- #ifdef SCC
- sccstop(); /* brute force ! */
- #endif
- #ifdef PACKET
- pkt_suspend(); /* see pktdrvr.c */
- #endif
- }
- stop_timer(&Statustimer);
- uchtimer(); /* disconnect the timer interrupt*/
- return(1);
- }
-
- /*----------------------------------------------------------------------*
- *-----------------------------------------------------------------------*/
- static void near dos_restore(Doslock *dl)
- {
- #ifdef PACKET
- extern INTERRUPT (*Pkvec[])();
- #endif
-
- /*-------------------------------------------------------------------*
- * restore the screen layout *
- *--------------------------------------------------------------------*/
- puttext(dl->tr.winleft, dl->tr.wintop,
- dl->tr.winright, dl->tr.winbottom,
- dl->sbuf);
- gotoxy(dl->tr.curx,dl->tr.cury);
- xfree(dl->sbuf);
-
- /*-------------------------------------------------------------------*
- * restore our irq's *
- * SEE THE CHANGES IN THE PARTICULAR xxx_init() and xxx_stop() rtns. *
- * dk5dc *
- *--------------------------------------------------------------------*/
- if (Swap) {
- #ifdef ASY
- int i;
- struct asy *asyp;
-
- for(i=0;i < ASY_MAX;i++){
- asyp = &Asy[i];
- if(asyp->iface == NULLIF)
- continue;
- asy_init(i,asyp->iface,0,0,0,0,0);
- asy_speed(i,asyp->speed);
- }
- #endif
- #ifdef SCC
- sccreact(); /* new function in scc.c dk5dc */
- #endif
- #ifdef PACKET
- pkt_restore(); /* see pktdrvr.c*/
- #endif
- }
- chtimer(btick); /* rechain the timer interrupt */
- start_timer(&Statustimer);
- }
-
- doswap(int argc,char *argv[],void *p)
- {
- return setbool(&Swap,"EMS/XMS/FILE swapping",argc,argv);
- }
-
- /* Keyboard interrupt handler */
- void
- kbint()
- {
- int c, sig = 0;
-
- while((c = kbraw()) != -1 && Keyboard.cnt < KBSIZE){
- sig = 1;
- *Keyboard.wp++ = c;
- if(Keyboard.wp == &Keyboard.buf[KBSIZE])
- Keyboard.wp = Keyboard.buf;
- Keyboard.cnt++;
- }
- if(sig){
- psignal(&Keyboard,0);
- }
- }
-
- static int near
- kbchar()
- {
- unsigned char c;
- int i_state = dirps();
-
- while(Keyboard.cnt == 0)
- pwait(&Keyboard);
- Keyboard.cnt--;
- restore(i_state);
- c = *Keyboard.rp++;
- if(Keyboard.rp == &Keyboard.buf[KBSIZE])
- Keyboard.rp = Keyboard.buf;
- return c;
- }
-
- /* Read characters from the keyboard, translating them to "real" ASCII.
- * If none are ready, block. The F-10 key is special; translate it to -2.
- */
- int
- kbread()
- {
- int c;
-
- if((c = kbchar()) == 0){
- /* Lead-in to a special char */
- switch(c = kbchar()){
- case 3: /* NULL (bizzare!) */
- c = 0;
- break;
- case 83: /* DEL key */
- c = 0x7f;
- break;
- case 68: /* F10 - used as command escape */
- c = -2;
- break;
- case 67: /* F9 temporarily used */
- case 0x71: /* ALT-F10 - used as trace screen */
- c = -13;
- break;
- case 80: /* down */
- c = 0x10;
- break;
- case 72: /* up */
- c = 0x0f;
- break;
- default:
- if(c > 58 && c < 67) /* F1 to F8 */
- c = (c - 56) * -1;
- else /* Dunno what it is */
- c = -1;
- }
- }
- return c;
- }
-
- /* Install hardware interrupt handler.
- * Takes IRQ numbers from 0-7 (0-15 on AT) and maps to actual 8086/286 vectors
- * Note that bus line IRQ2 maps to IRQ9 on the AT
- */
- int
- setirq(irq,handler)
- unsigned irq;
- INTERRUPT (*handler)();
- {
- /* Set interrupt vector */
- if(irq < 8){
- setvect(8+irq,handler);
- } else if(irq < 16){
- Isat = 1;
- setvect(0x70 + irq - 8,handler);
- } else {
- return -1;
- }
- return 0;
- }
-
- /* Return pointer to hardware interrupt handler.
- * Takes IRQ numbers from 0-7 (0-15 on AT) and maps to actual 8086/286 vectors
- */
- INTERRUPT
- (*getirq(irq))()
- unsigned int irq;
- {
- /* Set interrupt vector */
- if(irq < 8){
- return getvect(8+irq);
- } else if(irq < 16){
- return getvect(0x70 + irq - 8);
- } else {
- return NULLVIFP;
- }
- }
-
- /* Disable hardware interrupt */
- int
- maskoff(irq)
- unsigned irq;
- {
- if(irq < 8){
- setbit(0x21,(char)(1<<irq));
- } else if(irq < 16){
- irq -= 8;
- setbit(0xa1,(char)(1<<irq));
- } else {
- return -1;
- }
- return 0;
- }
-
- /* Enable hardware interrupt */
- int
- maskon(irq)
- unsigned irq;
- {
- if(irq < 8){
- clrbit(0x21,(char)(1<<irq));
- } else if(irq < 16){
- irq -= 8;
- clrbit(0xa1,(char)(1<<irq));
- } else {
- return -1;
- }
- return 0;
- }
-
- /* Return 1 if specified interrupt is enabled, 0 if not, -1 if invalid */
- int
- getmask(irq)
- unsigned irq;
- {
- if(irq < 8)
- return (inportb(0x21) & (1 << irq)) ? 0 : 1;
- else if(irq < 16){
- irq -= 8;
- return (inportb(0xa1) & (1 << irq)) ? 0 : 1;
- } else
- return -1;
- }
-
- /* Called from assembler stub linked to BIOS interrupt 1C, called on each
- * hardware clock tick. Signal a clock tick to the timer process.
- */
- void
- ctick()
- {
- Tick++;
- psignal(&Tick,1);
- }
-
- /* Called from the timer process on every tick. NOTE! This function
- * can NOT be called at interrupt time because it calls the BIOS
- */
- void
- pctick()
- {
- static long oldt; /* Value of bioscnt() on last call */
- static long days; /* # of times bioscnt() has rolled over */
-
- /* Update the time-since-boot */
- long t = bioscnt();
-
- if(t < oldt)
- days++; /* bioscnt has rolled past midnight */
- oldt = t;
- Clock = (days * 0x1800b0L) + t - Starttime;
- }
-
- /* Set bit(s) in I/O port */
- void
- setbit(port,bits)
- unsigned port;
- char bits;
- {
- outportb(port,(char)inportb(port)|bits);
- }
-
- /* Clear bit(s) in I/O port */
- void
- clrbit(port,bits)
- unsigned port;
- char bits;
- {
- outportb(port,(char)(inportb(port) & ~bits));
- }
-
- /* Set or clear selected bits(s) in I/O port */
- void
- writebit(port,mask,val)
- unsigned port;
- char mask;
- int val;
- {
- char x = inportb(port);
-
- if(val)
- x |= mask;
- else
- x &= ~mask;
-
- outportb(port,x);
- }
-
- /* Convert a pointer to a long integer */
- long
- ptol(p)
- void *p;
- {
- long x = FP_OFF(p);
-
- #ifdef LARGEDATA
- x |= (long)FP_SEG(p) << 16;
- #endif
- return x;
- }
- void *
- ltop(l)
- long l;
- {
- unsigned seg = (unsigned)(l >> 16);
- unsigned offset = (unsigned)l;
-
- return MK_FP(seg,offset);
- }
- void
- sysreset()
- {
- void (*foo) __ARGS((void));
-
- foo = MK_FP(0xffff,0); /* FFFF:0000 is hardware reset vector */
- (*foo)();
- }
- void
- newscreen(sp)
- struct session *sp;
- {
- if(sp != NULLSESSION)
- sp->screen = mxallocw(sizeof(struct screen));
- }
- void
- freescreen(sp)
- struct session *sp;
- {
- if(sp == NULLSESSION || sp->screen == NULLSCREEN)
- return;
- if(sp->screen->save != NULLCHAR)
- xfree(sp->screen->save);
- xfree((char *)sp->screen);
- sp->screen = NULLSCREEN; /* finish the job */
- }
-
- /* Reallocate screen buffers */
- static void near
- realloc_screen(int size)
- {
- int i;
- char *osave, *newsave;
- struct session *sp;
-
- for(i = 0, sp = Sessions; i < Nsessions; sp++, i++)
- if(sp->type != FREE) {
- if(sp->screen->save != 0) {
- newsave = mxallocw(size);
- if (FP_SEG(newsave) < FP_SEG(sp->screen->save)) {
- memcpy(newsave,sp->screen->save,size);
- osave = sp->screen->save;
- sp->screen->save = newsave;
- xfree(osave);
- } else
- xfree(newsave);
- }
- }
- }
-
- /* Save specified session screen and resume console screen */
- void
- swapscreen(old,new)
- struct session *old,*new;
- {
- int size;
- struct text_info tr;
-
- if(old == new)
- return; /* Nothing to do */
-
- gettextinfo(&tr);
- size = 2 * tr.screenheight * tr.screenwidth;
- if(old != NULLSESSION){
- /* Save old screen */
- if(old->screen->save == NULLCHAR)
- old->screen->save = mxallocw(size);
- if(old->screen->save != NULLCHAR){
- if(old->split){
- window(1,3,80,Nrows);
- tr.winbottom = Nrows;
- }
- gettext(tr.winleft,tr.wintop,tr.winright,
- tr.winbottom,old->screen->save);
- }
- old->screen->row = tr.cury;
- old->screen->col = tr.curx;
- }
- if(new != NULLSESSION){
- /* Load new screen */
- if(new->screen->save != NULLCHAR){
- if(new->split)
- window(1,3,80,Nrows-2);
- else {
- window(1,3,80,Nrows);
- tr.winbottom = Nrows;
- }
- clrscr();
- puttext(tr.winleft,tr.wintop,tr.winright,
- tr.winbottom,new->screen->save);
- gotoxy(new->screen->col,new->screen->row);
- /* Free the memory (saves 4K on a continuous basis) */
- xfree(new->screen->save);
- new->screen->save = NULLCHAR;
- } else {
- clrscr(); /* Start with a fresh slate */
- if(new->split){
- new->tsavex = new->bsavex = 1;
- new->tsavey = 2;
- new->bsavey = 24;
- window(1,Nrows-1,80,Nrows);
- cputs("_\b");
- window(1,3,80,Nrows-2);
- }
- }
- }
- realloc_screen(size);
- alert(Display,(void *)1); /* Wake him up */
- }
-
- void
- display(int i,void *v1,void *v2)
- {
- /* This is very tricky code. Because the value of "Current" can
- * change any time we do a pwait, we have to be careful to detect
- * any change and go back and start again.
- */
- for(;;){
- int c;
- struct session *sp = Current;
-
- if(sp->morewait) {
- pwait(&sp->row);
- if(sp != Current || sp->row <= 0) {
- /* Current changed value, or the user
- * hasn't really hit a key
- */
- continue;
- }
- /* Erase the prompt */
- cputs("\r \r");
- }
- sp->morewait = 0;
-
- if((c = rrecvchar(sp->output)) == -1){
- /* the alert() in swapscreen will cause this to
- * return -1 when current changes
- */
- pwait(NULL); /* Prevent a nasty loop */
- continue;
- }
- if(sp != Command) {
- textattr(WHITE);
- }
- putch(c);
-
- textattr(LIGHTGRAY);
-
- if(sp->record != NULLFILE && c != '\r') {
- fputc(c,sp->record);
- }
- if(sp->flowmode && c == '\n' && --sp->row <= 0) {
- cputs("--More--");
- sp->morewait = 1;
- }
- }
- }
-
-
- /* Return time since startup in milliseconds. If the system has an
- * 8254 clock chip (standard on ATs and up) then resolution is improved
- * below 55 ms (the clock tick interval) by reading back the instantaneous
- * value of the counter and combining it with the global clock tick counter.
- * Otherwise 55 ms resolution is provided.
- *
- * Reading the 8254 is a bit tricky since a tick could occur asynchronously
- * between the two reads. The tick counter is examined before and after the
- * hardware counter is read. If the tick counter changes, try again.
- * Note: the hardware counter counts down from 65536.
- */
- int32
- msclock()
- {
- int32 hi;
- int16 lo, count[4]; /* extended (48-bit) counter of timer clocks */
-
- if(!Isat)
- return Clock * MSPTICK;
-
- do {
- hi = Clock + Tick;
- lo = clockbits();
- } while(hi != Clock + Tick);
-
- count[0] = 0;
- count[1] = hi >> 16;
- count[2] = hi;
- count[3] = -lo;
- longmul(11,4,count); /* The ratio 11/13125 is exact */
- longdiv(13125,4,count);
- return ((long)count[2] << 16) + count[3];
- }
-
- /* Return clock in seconds */
- int32
- secclock()
- {
- int32 hi;
- int16 lo, count[4]; /* extended (48-bit) counter of timer clocks */
-
- if(!Isat)
- return (Clock * MSPTICK) / 1000L;
-
- do {
- hi = Clock + Tick;
- lo = clockbits();
- } while(hi != Clock + Tick);
-
- count[0] = 0;
- count[1] = hi >> 16;
- count[2] = hi;
- count[3] = -lo;
- longmul(11,4,count); /* The ratio 11/13125 is exact */
- longdiv(13125,4,count);
- longdiv(1000,4,count); /* Convert to seconds */
- return ((long)count[2] << 16) + count[3];
- }
-
-